package cn.chiship.sdk.third.core.wx.util;

import java.nio.charset.StandardCharsets;
import java.security.AlgorithmParameters;
import java.security.Key;
import java.security.NoSuchAlgorithmException;
import java.security.Security;
import java.security.spec.InvalidParameterSpecException;
import java.util.Base64;

import javax.crypto.Cipher;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;

import cn.chiship.sdk.core.base.BaseResult;
import cn.chiship.sdk.core.exception.ExceptionUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import org.bouncycastle.jce.provider.BouncyCastleProvider;

/**
 * 微信私密数据
 *
 * @author lijian
 */
public class WxBizDataCrypt {

	/**
	 * 加密方式
	 */
	private static String keyAlgorithm = "AES";

	private static boolean initialized = false;

	/**
	 * 用于Base64解密
	 */
	private Base64.Decoder decoder = Base64.getDecoder();

	/**
	 * 待解密的数据
	 */
	private String originalContent;

	/**
	 * 会话密钥sessionKey
	 */
	private String encryptKey;

	/**
	 * 加密算法的初始向量
	 */
	private String iv;

	public WxBizDataCrypt(String originalContent, String encryptKey, String iv) {
		this.originalContent = originalContent;
		this.encryptKey = encryptKey;
		this.iv = iv;
	}

	/**
	 * AES解密 填充模式AES/CBC/PKCS7Padding 解密模式128
	 * @return 结果 解密后的信息对象
	 */
	public BaseResult decryptData() {
		initialize();
		try {
			/**
			 * 数据填充方式
			 */
			Cipher cipher = Cipher.getInstance("AES/CBC/PKCS7Padding");
			Key sKeySpec = new SecretKeySpec(decoder.decode(this.encryptKey), keyAlgorithm);
			/**
			 * 初始化
			 */
			cipher.init(Cipher.DECRYPT_MODE, sKeySpec, generateIv(decoder.decode(this.iv)));
			byte[] data = cipher.doFinal(decoder.decode(this.originalContent));
			String dataResult = new String(data, StandardCharsets.UTF_8);
			JSONObject json = JSON.parseObject(dataResult);
			return BaseResult.ok(json);
		}
		catch (Exception e) {
			return BaseResult.error(ExceptionUtil.formatException(e));
		}
	}

	/**
	 * BouncyCastle作为安全提供，防止我们加密解密时候因为jdk内置的不支持改模式运行报错。
	 **/
	private static void initialize() {
		if (initialized) {
			return;
		}
		Security.addProvider(new BouncyCastleProvider());
		initialized = true;
	}

	/**
	 * 生成iv
	 * @param iv
	 * @return 结果
	 * @throws NoSuchAlgorithmException
	 * @throws InvalidParameterSpecException
	 */
	private static AlgorithmParameters generateIv(byte[] iv)
			throws NoSuchAlgorithmException, InvalidParameterSpecException {
		AlgorithmParameters params = AlgorithmParameters.getInstance(keyAlgorithm);
		params.init(new IvParameterSpec(iv));
		return params;
	}

}
